home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Resources / Online / Term / Extras / Source / term-source.lha / Chat.c < prev    next >
C/C++ Source or Header  |  1996-10-20  |  8KB  |  450 lines

  1. /*
  2. **    Chat.c
  3. **
  4. **    Chat support code
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16.     /* Maximum number of characters to enter per line */
  17.  
  18. #define CHAT_LINE_SIZE    512
  19.  
  20.     /* Local data */
  21.  
  22. STATIC struct List    *ChatList;
  23. STATIC struct Node    *ChatNode;
  24. STATIC STRPTR         ChatBuffer,
  25.                      ChatUndo,
  26.                      ChatWork,
  27.                      ChatTemp;
  28. STATIC ULONG         ChatPosition;
  29. STATIC Object        *ChatGadget;
  30. STATIC BOOL             ChatWasActive;
  31.  
  32.     /* HideChatGadget():
  33.      *
  34.      *    Remove the chat gadget, but don't free the buffers.
  35.      */
  36.  
  37. VOID
  38. HideChatGadget()
  39. {
  40.     if(ChatGadget)
  41.     {
  42.         GetAttr(STRINGA_BufferPos,ChatGadget,&ChatPosition);
  43.  
  44.         RemoveGList(Window,(struct Gadget *)ChatGadget,1);
  45.  
  46.         DisposeObject(ChatGadget);
  47.  
  48.         ChatGadget = NULL;
  49.     }
  50. }
  51.  
  52.     /* DeleteChatGadget():
  53.      *
  54.      *    Remove the chat gadget, also take care of the buffers.
  55.      */
  56.  
  57. VOID
  58. DeleteChatGadget()
  59. {
  60.     HideChatGadget();
  61.  
  62.     FreeVecPooled(ChatBuffer);
  63.     ChatBuffer = NULL;
  64.  
  65.     DeleteList(ChatList);
  66.     ChatList = NULL;
  67. }
  68.  
  69.     /* UpdateChatGadget():
  70.      *
  71.      *    Redraw the chat gadget imagery.
  72.      */
  73.  
  74. VOID
  75. UpdateChatGadget()
  76. {
  77.     if(ChatGadget)
  78.     {
  79.         struct RastPort    *RPort;
  80.         LONG Left,Right,Top;
  81.  
  82.         RPort = Window->RPort;
  83.  
  84.             /* Draw the separator bar */
  85.  
  86.         if(StatusWindow || Config->ScreenConfig->StatusLine == STATUSLINE_DISABLED)
  87.             Top = UserFontHeight;
  88.         else
  89.             Top = StatusDisplayHeight + UserFontHeight;
  90.  
  91.         Top        = Window->Height - (Window->BorderBottom + Top + 2);
  92.         Left    = Window->BorderLeft;
  93.         Right    = Window->Width - (Window->BorderRight + 1);
  94.  
  95.         SetAPen(RPort,Pens[SHADOWPEN]);
  96.         RectFill(RPort,Left,Top,Right,Top);
  97.  
  98.         Top++;
  99.  
  100.         SetAPen(RPort,Pens[SHINEPEN]);
  101.         RectFill(RPort,Left,Top,Right,Top);
  102.  
  103.             /* Redraw the gadget */
  104.  
  105.         RefreshGList((struct Gadget *)ChatGadget,Window,NULL,1);
  106.     }
  107. }
  108.  
  109.     /* ActivateChat(BOOL Reactivate):
  110.      *
  111.      *    Activate the chat gadget.
  112.      */
  113.  
  114. VOID
  115. ActivateChat(BOOL Reactivate)
  116. {
  117.     if(ChatGadget)
  118.     {
  119.         if(Reactivate)
  120.             Reactivate = ChatWasActive;
  121.         else
  122.             Reactivate = TRUE;
  123.  
  124.         if(Reactivate)
  125.             ActivateGadget((struct Gadget *)ChatGadget,Window,NULL);
  126.     }
  127. }
  128.  
  129.     /* CreateChatGadget():
  130.      *
  131.      *    Create the chat gadget and add it to the main window.
  132.      */
  133.  
  134. BOOL
  135. CreateChatGadget()
  136. {
  137.     ChatWasActive = TRUE;
  138.  
  139.         /* Allocate the history list */
  140.  
  141.     if(!ChatList)
  142.     {
  143.         if(!(ChatList = CreateList()))
  144.             return(FALSE);
  145.  
  146.         ChatNode = NULL;
  147.     }
  148.  
  149.         /* Allocate the undo/work/editing buffers */
  150.  
  151.     if(!ChatBuffer)
  152.     {
  153.         if(!(ChatBuffer = (STRPTR)AllocVecPooled(5 * CHAT_LINE_SIZE,MEMF_ANY | MEMF_CLEAR)))
  154.         {
  155.             DeleteChatGadget();
  156.  
  157.             return(FALSE);
  158.         }
  159.         else
  160.         {
  161.             ChatUndo = ChatBuffer    + CHAT_LINE_SIZE;
  162.             ChatWork = ChatUndo        + CHAT_LINE_SIZE;
  163.             ChatTemp = ChatWork        + CHAT_LINE_SIZE;
  164.         }
  165.     }
  166.  
  167.         /* Finally create the gadget */
  168.  
  169.     if(!ChatGadget)
  170.     {
  171.         STATIC struct Hook ChatHook;
  172.  
  173.         LONG Bottom = Window->BorderBottom + UserFontHeight - 1;
  174.  
  175.         InitHook(&ChatHook,(HOOKFUNC)CommonEditRoutine,NULL);
  176.  
  177.         if(!StatusWindow && Config->ScreenConfig->StatusLine != STATUSLINE_DISABLED && !Config->ScreenConfig->SplitStatus)
  178.             Bottom += StatusDisplayHeight;
  179.  
  180.         if(!(ChatGadget = NewObject(NULL,STRGCLASS,
  181.             GA_Left,                Window->BorderLeft,
  182.             GA_Height,                UserFontHeight,
  183.             GA_RelBottom,            -Bottom,
  184.             GA_RelWidth,            -(Window->BorderLeft + Window->BorderRight),
  185.             GA_TabCycle,            FALSE,
  186.             GA_ID,                    CHAT_GadgetID,
  187.             GA_RelVerify,            TRUE,
  188.             GA_Immediate,            TRUE,
  189.             STRINGA_TextVal,        ChatBuffer,
  190.             STRINGA_MaxChars,        CHAT_LINE_SIZE-1,
  191.             STRINGA_Buffer,            ChatBuffer,
  192.             STRINGA_BufferPos,        ChatPosition,
  193.             STRINGA_UndoBuffer,        ChatUndo,
  194.             STRINGA_WorkBuffer,        ChatWork,
  195.             STRINGA_NoFilterMode,    TRUE,
  196.             STRINGA_EditHook,        &ChatHook,
  197.  
  198.                 /* NOTE: This should really look like below, */
  199.                 /*       according to the BOOPSI documentation. */
  200.                 /*       Even worse, the pen numbers are in reality */
  201.                 /*       truncated to a maximum of colour # 15. */
  202.  
  203.     /*        STRINGA_Pens,            ((LONG)Pens[BACKGROUNDPEN] << 16) | Pens[TEXTPEN], */
  204.     /*        STRINGA_ActivePens,        ((LONG)Pens[BACKGROUNDPEN] << 16) | Pens[TEXTPEN], */
  205.  
  206.             STRINGA_Pens,            (Pens[BACKGROUNDPEN] << 8) | Pens[TEXTPEN],
  207.             STRINGA_ActivePens,        (Pens[BACKGROUNDPEN] << 8) | Pens[TEXTPEN],
  208.         TAG_DONE)))
  209.         {
  210.             DeleteChatGadget();
  211.  
  212.             return(FALSE);
  213.         }
  214.         else
  215.             AddGList(Window,(struct Gadget *)ChatGadget,(UWORD)~0,1,NULL);
  216.     }
  217.  
  218.     return(TRUE);
  219. }
  220.  
  221.     /* HandleChatGadget(UWORD GadgetCode):
  222.      *
  223.      *    Process the input forwarded by the chat line gadget.
  224.      */
  225.  
  226. VOID
  227. HandleChatGadget(UWORD GadgetCode)
  228. {
  229.     BOOL Activate,NeedChange,AddIt;
  230.     UWORD Code,Qualifier;
  231.  
  232.     Activate    = TRUE;
  233.     NeedChange    = FALSE;
  234.     Code        = GadgetCode & 0xFF;
  235.     Qualifier    = GadgetCode >> 8;
  236.  
  237.     switch(Qualifier)
  238.     {
  239.         case 0xFF:
  240.  
  241.             switch(Code)
  242.             {
  243.                 case CONTROL_('S'):
  244.                 case CONTROL_('Q'):
  245.  
  246.                     ChatTemp[0] = Code;
  247.                     SendInputTextBuffer(ChatTemp,1,TRUE,TRUE);
  248.                     break;
  249.  
  250.                 case '\r':
  251.  
  252.                     LimitedStrcpy(CHAT_LINE_SIZE,ChatTemp,ChatBuffer);
  253.  
  254.                         /* Add the line unless it is already in the history list. */
  255.  
  256.                     AddIt = TRUE;
  257.  
  258.                     if(ChatNode)
  259.                     {
  260.                         if(!Stricmp(ChatNode->ln_Name,ChatTemp))
  261.                             AddIt = FALSE;
  262.                     }
  263.  
  264.                     if(AddIt)
  265.                     {
  266.                         struct Node *Node;
  267.  
  268.                         if(Node = CreateNode(ChatTemp))
  269.                             AddTail(ChatList,Node);
  270.                     }
  271.  
  272.                     ChatNode = NULL;
  273.                     NeedChange = TRUE;
  274.  
  275.                     LimitedStrcat(CHAT_LINE_SIZE,ChatTemp,"\\r");
  276.                     SerialCommand(ChatTemp);
  277.                     break;
  278.  
  279.                 case '\n':
  280.  
  281.                     Activate = FALSE;
  282.                     break;
  283.             }
  284.  
  285.             break;
  286.  
  287.         default:
  288.  
  289.                 /* Clear the history list when pressing Amiga+Del/Amiga+Backspace */
  290.  
  291.             if((Qualifier & (AMIGARIGHT | AMIGALEFT)) && (Code == DEL_CODE || Code == BACKSPACE_CODE))
  292.             {
  293.                 FreeList(ChatList);
  294.  
  295.                 ChatNode = NULL;
  296.  
  297.                 NeedChange = TRUE;
  298.  
  299.                 break;
  300.             }
  301.  
  302.                 /* This looks like a function key. Send the corresponding macro. */
  303.  
  304.             if(Code >= F01_CODE && Code <= F10_CODE)
  305.             {
  306.                 STRPTR String;
  307.                 LONG Index;
  308.  
  309.                 Index = Code - F01_CODE;
  310.  
  311.                     /* Pick the right macro */
  312.  
  313.                 if(Qualifier & CONTROL_KEY)
  314.                     String = MacroKeys->Keys[3][Index];
  315.                 else
  316.                 {
  317.                     if(Qualifier & ALT_KEY)
  318.                         String = MacroKeys->Keys[2][Index];
  319.                     else
  320.                     {
  321.                         if(Qualifier & SHIFT_KEY)
  322.                             String = MacroKeys->Keys[1][Index];
  323.                         else
  324.                             String = MacroKeys->Keys[0][Index];
  325.                     }
  326.                 }
  327.  
  328.                     /* Anything to do? */
  329.  
  330.                 if(String[0])
  331.                 {
  332.                         /* This should really insert the macro at the current
  333.                          * cursor position, but due to some strange reasons
  334.                          * we can't get the position reliably.
  335.                          */
  336.  
  337.                     LimitedStrcpy(CHAT_LINE_SIZE,ChatTemp,ChatBuffer);
  338.                     LimitedStrcat(CHAT_LINE_SIZE,ChatTemp,String);
  339.  
  340.                     SetGadgetAttrs((struct Gadget *)ChatGadget,Window,NULL,
  341.                         STRINGA_TextVal,    ChatTemp,
  342.                         STRINGA_BufferPos,    strlen(ChatTemp),
  343.                     TAG_DONE);
  344.                 }
  345.  
  346.                 break;
  347.             }
  348.  
  349.                 /* The user pressed the cursor-up key to
  350.                  * scroll through the command history.
  351.                  */
  352.  
  353.             if(Code == CURSORUP)
  354.             {
  355.                     /* Shift key: jump to first command
  356.                      * history entry.
  357.                      */
  358.  
  359.                 if(Qualifier & SHIFT_KEY)
  360.                 {
  361.                     NeedChange = TRUE;
  362.  
  363.                     if(!IsListEmpty(ChatList))
  364.                         ChatNode = ChatList->lh_Head;
  365.                     else
  366.                         ChatNode = NULL;
  367.                 }
  368.                 else
  369.                 {
  370.                     if(ChatNode)
  371.                     {
  372.                         if(ChatNode->ln_Pred->ln_Pred)
  373.                         {
  374.                             NeedChange = TRUE;
  375.  
  376.                             ChatNode = ChatNode->ln_Pred;
  377.                         }
  378.                     }
  379.                     else
  380.                     {
  381.                         if(!IsListEmpty(ChatList))
  382.                         {
  383.                             NeedChange = TRUE;
  384.  
  385.                             ChatNode = ChatList->lh_TailPred;
  386.                         }
  387.                     }
  388.                 }
  389.             }
  390.  
  391.                 /* The user pressed the cursor-down key to
  392.                  * scroll through the command history.
  393.                  */
  394.  
  395.             if(Code == CURSORDOWN)
  396.             {
  397.                 NeedChange = TRUE;
  398.  
  399.                     /* Shift key: jump to last command
  400.                      * history entry.
  401.                      */
  402.  
  403.                 if(Qualifier & SHIFT_KEY)
  404.                 {
  405.                     if(!IsListEmpty(ChatList))
  406.                         ChatNode = ChatList->lh_TailPred;
  407.                     else
  408.                         ChatNode = NULL;
  409.                 }
  410.                 else
  411.                 {
  412.                     if(ChatNode)
  413.                     {
  414.                         if(ChatNode->ln_Succ->ln_Succ)
  415.                             ChatNode = ChatNode->ln_Succ;
  416.                         else
  417.                             ChatNode = NULL;
  418.                     }
  419.                 }
  420.             }
  421.  
  422.             break;
  423.     }
  424.  
  425.         /* Check if we have to update the string gadget contents. */
  426.  
  427.     if(NeedChange)
  428.     {
  429.         SetGadgetAttrs((struct Gadget *)ChatGadget,Window,NULL,
  430.             STRINGA_TextVal,ChatNode ? ChatNode->ln_Name : "",
  431.         TAG_DONE);
  432.     }
  433.  
  434.     ChatWasActive = Activate;
  435.  
  436.     if(Activate)
  437.         ActivateGadget((struct Gadget *)ChatGadget,Window,NULL);
  438. }
  439.  
  440.     /* MarkChatGadgetAsActive():
  441.      *
  442.      *    Remember that the chat gadget was activated.
  443.      */
  444.  
  445. VOID
  446. MarkChatGadgetAsActive()
  447. {
  448.     ChatWasActive = TRUE;
  449. }
  450.